#include "StdAfx.h"

#include "FirstIntersectionResult.h"
#include "SecondIntersectionResult.h"

#include "FlatRectangle.h"

FlatRectangle::FlatRectangle(Point p0, Point p1, Point p2, const Color& color) : 
	_vec1(p1 - p0), _vec2(p2 - p0), _p0(p0)
	, _xOfNormal(_vec1.Y * _vec2.Z - _vec1.Z * _vec2.Y)
	, _yOfNormal(_vec1.Z * _vec2.X - _vec1.X * _vec2.Z)
	, _zOfNormal(_vec1.X * _vec2.Y - _vec1.Y * _vec2.X)
	, _plain(Ray(p0, Point(_vec1.Y * _vec2.Z - _vec1.Z * _vec2.Y, _vec1.Z * _vec2.X - _vec1.X * _vec2.Z, _vec1.X * _vec2.Y - _vec1.Y * _vec2.X)), Color(0, 0, 0))
	, _color(color)
{
}

void FlatRectangle::WhereIntersects(const Ray& ray, FirstIntersectionResult& result)
{
	_plain.WhereIntersects(ray, result);
	double t = result.Distance;

	if (t == std::numeric_limits<double>::infinity() || t <= 0)
		return;
	
	
	Point pointOnPlain(ray.D);
	pointOnPlain *= t;
	pointOnPlain += ray.P;

	double temp;
	if (_zOfNormal != 0)
		temp = ((pointOnPlain.X - _p0.X) * _vec2.Y - (pointOnPlain.Y - _p0.Y) * _vec2.X) / _zOfNormal;
	else if (_yOfNormal != 0)
		temp = ((pointOnPlain.Z - _p0.Z) * _vec2.X - (pointOnPlain.X - _p0.X) * _vec2.Z) / _yOfNormal;
	else
		temp = ((pointOnPlain.Y - _p0.Y) * _vec2.Z - (pointOnPlain.Z - _p0.Z) * _vec2.Y) / _xOfNormal;

	if ((temp >= 0) && (temp <= 1))
	{
		if (_zOfNormal != 0)
			temp = ((pointOnPlain.Y - _p0.Y) * _vec1.X - (pointOnPlain.X - _p0.X) * _vec1.Y) / _zOfNormal;
		else if (_yOfNormal != 0)
			temp = ((pointOnPlain.X - _p0.X) * _vec1.Z - (pointOnPlain.Z - _p0.Z) * _vec1.X) / _yOfNormal;
		else
			temp = ((pointOnPlain.Z - _p0.Z) * _vec1.Y - (pointOnPlain.Y - _p0.Y) * _vec1.Z) / _xOfNormal;

		if ((temp >= 0) && (temp <= 1))
			result.Set(t, this);
		else
			result.Set(this);
	}
	else
		result.Set(this);
}

void FlatRectangle::ColorAtIntersection(SecondIntersectionResult& result, const Point&, const Ray&)
{
	result.ColorAtPoint = _color;
}

Direction FlatRectangle::NormalAtPoint(FirstIntersectionResult& first, const Point& point)
{
	return _plain.NormalAtPoint(first, point);
}

FlatRectangle::~FlatRectangle() {}
